use std::sync::Arc;

use async_trait::async_trait;
use rig::{agent::{Agent, AgentBuilder}, completion::Prompt, providers::openai::{self, CompletionModel}};

use common::compose::{CallBox, CallCore, ContextBox, FError};

pub struct AgentConfig {
    pub temperature: f32,
    pub max_tokens: usize,
    pub system: String,
}

pub fn init_agent<'a>(system: &'a str, api_key: &'a str) -> CallBox<'a, String, String> {
    let client = openai::Client::from_url(api_key, "https://api.hunyuan.cloud.tencent.com/v1");
    let model = client.completion_model("hunyuan-turbos-latest");
    let agent = AgentBuilder::new(model)
        .temperature(1.3)
        .preamble(system)
        .max_tokens(60000)
        .build();

    struct AgentWrapper {
        agent: Agent<CompletionModel>,
    }

    #[async_trait]
    impl CallCore<String, String> for AgentWrapper {
        async fn run(&self, prompt: String, _: ContextBox) -> Result<String, FError> {
            let chat_response = self.agent.prompt(prompt)
                .await
                .map_err(|e| FError::Generic(Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))))?;
            Ok(chat_response)
        }
    }

    Arc::new(Box::new(AgentWrapper { agent }))
}


#[cfg(test)]
mod tests {
    use common::{compose::make_empty_ctx, tools::{get_file_content, write_file_content}};

    use super::*;
    use std::env;
    use tokio::runtime::Runtime;

    #[test]
    fn test_init_agent() {
        dotenvy::from_path("../../.env").ok();
        // 从环境变量获取API密钥，如果没有设置则跳过测试
        let api_key = match env::var("HUNYUNA_API_KEY") {
            Ok(key) => key,
            Err(_) => {
                println!("跳过测试：未设置 HUNYUNA_API_KEY 环境变量");
                return;
            }
        };

        // 创建系统提示
        let system = r#"
请将文本内容专业地翻译为中文，要求：

1. 保持原文语义完整性和逻辑结构
2. 使用书面正式语体，避免口语化表达
3. 对专业术语进行准确转换
4. 保留原始段落格式和标点规范
5. 文化意象做本土化适配处理
6. 完成初稿后进行两次交叉校验，确保翻译质量
"#;

        // 初始化Agent
        let agent = init_agent(system, &api_key);

        // 创建Tokio运行时来执行异步代码
        let rt = Runtime::new().unwrap();

        let file_path = "E:/project/yesdoc/dioxus/docs/en/cookbook/bundling.md";
        let content = get_file_content(file_path).unwrap();

        // 执行异步测试
        let result = rt.block_on(async {
            // 发送测试提示
            let prompt = content;
            let response = agent.run(prompt.to_string(), make_empty_ctx()).await;

            // 验证响应
            assert!(response.is_ok(), "Agent应该返回一个有效的响应");
            let response_text = response.unwrap();

            // 验证响应不为空
            assert!(!response_text.is_empty(), "Agent的响应不应该为空");

            write_file_content("E:/project/yesdoc/dioxus/docs/en/cookbook/bundling_zh.md", &response_text).unwrap();

            Ok::<(), String>(())
        });

        // 确保测试成功完成
        assert!(result.is_ok());
    }

  }